import re

# Loads a 3D model
# Currently implements only OBJ models
class ModelLoader:
    def __init__(self,filename,mode='OBJ'):
        self.fn = filename
        self.mode = mode

    # Wrapper function, will call the correct function based on the file 
    # extension or mode. 
    def loadModel(self,filename = ''):
        if filename == '':
            filename = self.fn
        if re.match('.*\.obj$',filename):
            return self.loadObj(filename)
        else:
            if self.mode == 'OBJ':
                return self.loadObj(filename)
            else:
                return False

    # Loads an obj file
    # Returns a dictionary with the following entries:
    # verts: list of tuples representing vertices (3D)
    # textures: list of tuples representing texture coordinates (2D)
    # normals: list of tuples representing surface normals (3D)
    # faces: list of list of tuples representing faces; the tuple consist of 3 parts:
    #   1. Vertex index
    #   2. Texture coordinate index
    #   3. Surface normal index
    # 2) and 3) are optional, will be set to false if they are empty
    def loadObj(self, filename='') :
        V = [] #vertex
        T = [] #texcoords
        N = [] #normals
        F = [] #face indices

        vPattern = re.compile("^v\s+(.+)\s+(.+)\s+(.+)$")
        tPattern = re.compile("^vt\s+(.+)\s+(.+)$")
        nPattern = re.compile("^vn\s+(.+)\s+(.+)\s+(.+)$")
        
        fPattern = re.compile("""^f\s+(.+)\\r?$""")
     
        fh = open(filename)
        for line in fh:
            vRes = vPattern.search(line)
            if vRes:
                V.append((float(vRes.group(1)),float(vRes.group(2)),float(vRes.group(3))))
                pass
            tRes = tPattern.search(line)
            if tRes:
                T.append((float(tRes.group(1)),float(tRes.group(2))))
                pass
            nRes = nPattern.search(line)
            if nRes:
                N.append((float(nRes.group(1)),float(nRes.group(2)),float(nRes.group(3))))
                pass
        
            fRes = fPattern.search(line)
            if fRes:
                items = fRes.group(1).split(' ')
                face = []
                for grp in [x for x in items if x != '']:
                    if grp == '' or grp == ' ':
                        pass
                    values = []
                    for x in grp.split('/'):
                        if not x == '':
                            values.append(int(x))
                        else:
                            values.append(False)
                    while len(values) < 3:
                        values.append(False)
                    face.append(tuple(values))
                F.append(face)
         
        return {'verts':V, 'textures':T, 'normals':N, 'faces':F}
